/**
 * 计时器的挂件
 * 
 * 注意: 因为是挂件, 所以没有 sendStatus 这个方法.
 * 该挂件的 Pendant 实例需要调用 sendStatus 方法, 因此需要上层设置 sendStatus 方法
 */

import BreathingWall from '../comp/breathingWall';
import Curtain from '../comp/curtain';
import Meteors from '../comp/meteors';
import TimerPanel from '../comp/timerPanel';

import MyTimer from '../comp/myTimer';

/**
 * public 创建 Pendant 挂件方法
 * @param context
 */
function createPendant(context) {
  return new context.Pendant({
    require : ['zrender'],

    // 参数
    zr : null,
    width : 0,
    height : 0,

    // 逻辑
    /** @type {MyTimer} */
    timer : new MyTimer(),

    // UI
    /** @type {BreathingWall} */
    breathingWall : null,
    /** @type {Curtain} */
    curtain : null,
    /** @type {Meteors} */
    meteors : null,
    /** @type {TimerPanel} */
    timerPanel : null,

    init(libs, args) {
      let main = document.getElementById(args.dom);
      // 背景颜色
      if (args.backgroundColor) {
        main.style.background = args.backgroundColor;
      }

      this.zr = libs.zrender.init(main);
      this.width = this.zr.getWidth();
      this.height = this.zr.getHeight();

      // UI
      this.breathingWall = new BreathingWall({
        parent : this,
        zrender : libs.zrender,
        zrInstance : this.zr,
      });
      this.curtain = new Curtain({
        parent : this,
        zrender : libs.zrender,
        zrInstance : this.zr,
      });
      this.meteors = new Meteors({
        parent : this,
        zrender : libs.zrender,
        zrInstance : this.zr,
        timer : this.timer,
      });
      this.timerPanel = new TimerPanel({
        parent : this,
        zrender : libs.zrender,
        zrInstance : this.zr,
        timer : this.timer,
      });

      requestAnimationFrame(this.tick.bind(this));
    },

    destroy() {
      this.breathingWall.destroy();
      this.curtain.destroy();
      this.meteors.destroy();
      this.timerPanel.destroy();
    },

    tick() {
      this.timer.tick();

      this.breathingWall.tick();
      this.curtain.tick();
      this.meteors.tick();
      this.timerPanel.tick();
      requestAnimationFrame(this.tick.bind(this));
    },

    /* **********
     * 状态控制 *
     ********** */
    onMessage(name, arg) {
      switch (name) {
        case 'start': this.start(); break;
        case 'stop': this.stop(arg); break;
        case 'pause': this.pause(arg); break;
        case 'reset': this.reset(arg); break;
        case 'record': this.record(); break; // TODO 还未确定格式
        case 'undoPause': this.undoPause(arg); break;
      }
    },

    start() {
      if (!this.timer.start()) {
        console.log("计时器已经启动了");
        return;
      }

      this.timerPanel.color(false);
      this.sendStatus();
      // 动画部分
      this.curtain.animate();
      this.meteors.start();
    },

    stop(value) {
      if (!this.timer.pause(value)) {
        console.log("计时器还未启动");
        return;
      }
  
      this.timerPanel.color(true);
      this.sendStatus();
      // 动画部分
      this.curtain.animate();
      this.meteors.stop();
    },

    pause(value) {
      if (!this.timer.pause(value)) {
        console.log("计时器还未启动");
        return;
      }
      this.sendStatus();
      // 动画部分
      this.meteors.stop();
    },

    reset(value) {
      this.timer.reset(value);
      this.timerPanel.color(false);

      this.sendStatus();
      this.meteors.stop();
    },

    /**
     * 计次
     */
    record() {
      // 向后端发送计次的消息
      this.sendStatus();
    },

    /**
     * 撤销暂停 (前面暂停 / 停止后的时间仍然计入总时间)
     */
    undoPause(value) {
      if (!this.timer.undoPause(value)) {
        console.log("计时器已经启动了或还没有开始");
        return;
      }

      this.timerPanel.color(false);
      this.sendStatus();

      // 动画部分
      this.curtain.animate();
      this.meteors.start();
    },

    /*
     * 收集状态数据
     */
    collectInfo() {
      return {
        delta : this.timer.delta, // 1/10 秒, 数据
        // 计时器是否正在运行.
        // 暂停时也为 true, 重置或者在 0 时刻还未启动时为 false
        player : this.timer.playing,
        // 是否在暂停.
        pause : this.timer.pauseDelta >= 0
      };
    },

  });
};

// 对外开放哪些方法
export default createPendant;

